// 文件路径: dbms/service/RemoteDbmsService.java
package com.dbms.service;

import com.dbms.DbmsCore;
import com.dbms.common.QueryResult;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;

/**
 * 远程数据库管理系统服务实现类
 * 通过Socket与远程服务器通信，实现IDbmsService接口定义的数据库操作功能
 */
public class RemoteDbmsService implements IDbmsService {

    // 用于与远程服务器通信的Socket连接
    private final Socket socket;
    // 对象输出流，用于向服务器发送序列化对象（如请求）
    private final ObjectOutputStream oos;
    // 对象输入流，用于从服务器接收序列化对象（如响应）
    private final ObjectInputStream ois;

    // 当前登录的用户名，与服务器端保持同步
    private String currentUser;
    // 标记当前是否处于事务中，与服务器端保持同步
    private boolean inTransaction;

    /**
     * 构造方法：建立与远程数据库服务器的连接
     * @param host 远程服务器主机地址
     * @param port 远程服务器监听端口
     * @throws IOException 当Socket连接建立失败或流初始化失败时抛出
     * 注意：必须先初始化输出流，再初始化输入流，否则可能导致客户端与服务器端相互阻塞（死锁）
     */
    public RemoteDbmsService(String host, int port) throws IOException {
        this.socket = new Socket(host, port);
        // 输出流先于输入流创建，避免因双方等待对方建立流而导致的死锁
        this.oos = new ObjectOutputStream(socket.getOutputStream());
        this.ois = new ObjectInputStream(socket.getInputStream());
    }

    /**
     * 注册用户自定义函数（UDF）
     * 向远程服务器发送UDF注册请求，目前此功能尚未实现
     * @param functionName 自定义函数名称
     * @param sourceCode 自定义函数的源代码
     * @return 操作结果提示信息（当前返回未实现提示）
     */
    @Override
    public String registerUdf(String functionName, String sourceCode) {
        // TODO: 实现客户端到服务器的UDF注册请求
        // 目前，远程模式下此功能不可用
        return "失败: 远程UDF注册功能尚未实现。";
    }

    /**
     * 处理SQL语句并返回执行结果
     * 向远程服务器发送SQL执行请求，接收并处理服务器响应
     * @param sql 待执行的SQL语句
     * @return 包含执行结果的QueryResult对象，若发生异常则返回包含错误信息的结果
     */
    @Override
    public QueryResult processSql(String sql) {
        try {
            // 创建SQL执行请求对象
            Request request = new Request(sql);
            // 发送请求到服务器
            oos.writeObject(request);
            oos.flush(); // 强制刷新缓冲区，确保请求立即发送
            // 接收服务器返回的响应
            Response response = (Response) ois.readObject();

            // 更新客户端本地状态，与服务器保持一致
            this.currentUser = response.getCurrentUser();
            this.inTransaction = response.isInTransaction();

            // 返回服务器执行SQL的结果
            return response.getQueryResult();
        } catch (IOException | ClassNotFoundException e) {
            // 捕获通信异常或对象反序列化异常，返回包含错误信息的结果
            return new QueryResult("Connection error: " + e.getMessage());
        }
    }

    /**
     * 用户身份认证
     * 向远程服务器发送用户名和密码进行认证，同步服务器返回的认证结果和用户信息
     * @param username 用户名
     * @param password 密码
     * @return 认证成功返回true，失败或发生异常返回false
     */
    @Override
    public boolean authenticate(String username, String password) {
        try {
            // 创建包含认证信息的请求对象
            Request request = new Request(username, password);
            // 发送认证请求到服务器
            oos.writeObject(request);
            oos.flush(); // 强制刷新缓冲区
            // 接收服务器的认证响应
            Response response = (Response) ois.readObject();

            // 若认证成功，更新当前登录用户信息
            if (response.isSuccess()) {
                this.currentUser = response.getCurrentUser();
            }

            // 返回认证结果
            return response.isSuccess();
        } catch (IOException | ClassNotFoundException e) {
            // 捕获通信异常，打印堆栈信息并返回认证失败
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 获取当前登录用户
     * @return 当前登录的用户名，未登录时可能为null
     */
    @Override
    public String getCurrentUser() {
        return this.currentUser;
    }

    /**
     * 检查当前是否处于事务中
     * @return 处于事务中返回true，否则返回false
     */
    @Override
    public boolean isInTransaction() {
        return this.inTransaction;
    }

    /**
     * 关闭与远程服务器的连接
     * 释放Socket资源，断开网络连接
     * @throws IOException 当关闭Socket时发生I/O错误时抛出
     */
    @Override
    public void close() throws IOException {
        // 检查Socket是否存在且未关闭，确保安全关闭
        if (socket != null && !socket.isClosed()) {
            socket.close();
        }
    }
}